package net.yeah.mickey_zhouyou.util.fcs;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayDeque;
import java.util.Deque;

public class ReaderWrapper {

	private Reader reader;
	private Deque<Long> rc = new ArrayDeque<Long>();

	public long getCurrentRow() {
		return rc.size();
	}

	public long getCurrentColumn() {
		return rc.getFirst();
	}

	public ReaderWrapper(Reader reader) {
		this.reader = reader;
		rc.push(0L);
	}

	private Deque<Character> cache = new ArrayDeque<Character>();

	public char read() throws IOException, ReaderOverException {
		if (cache.isEmpty()) {
			char[] buf = new char[128];
			int l = this.reader.read(buf);
			if (l > 0)
				for (int i = 0; i < l; ++i)
					cache.add(buf[i]);
		}
		if (cache.isEmpty())
			throw new ReaderOverException();
		char res = cache.pop();
		if (res == '\n')
			rc.push(0L);
		else
			rc.push(rc.pop() + 1);
		return res;
	}

	public char readNotBlank() throws IOException, ReaderOverException {
		char res;
		do {
			res = read();
		} while (isBlank(res));
		return res;
	}

	public char look() throws IOException, ReaderOverException {
		if (cache.isEmpty())
			putback(read());
		return cache.getFirst();
	}

	public char lookNotBlank() throws IOException, ReaderOverException {
		char res = readNotBlank();
		putback(res);
		return res;
	}

	private boolean isBlank(char c) {
		if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
			return true;
		return false;
	}

	public String readAString() throws IOException, ReaderOverException {
		char r = readNotBlank();
		StringBuilder sb = new StringBuilder().append(r);
		if (r == '\'') {
			sb.append(r = read());
			while (r != '\'') {
				if (r == '\\')
					sb.deleteCharAt(sb.length() - 1).append(read());
				sb.append(r = read());
			}
		} else {
			while (r != ';' && r != '(' && r != ')' && r != '[' && r != '\''
					&& r != '.' && r != '=' && r != '<' && r != '>') {
				if (r == '\\')
					sb.deleteCharAt(sb.length() - 1).append(read());
				sb.append(r = readNotBlank());
			}
			sb.deleteCharAt(sb.length() - 1);
			putback(r);
		}
		return sb.toString();
	}

	public String readUntil(char c) throws IOException, ReaderOverException {
		StringBuilder sb = new StringBuilder();
		char r;
		do {
			sb.append(r = read());
		} while (r != c);
		return sb.toString();
	}

	public void putback(char c) {
		if (c == '\n')
			rc.pop();
		else
			rc.push(rc.pop() - 1);
		cache.push(c);
	}

}
